package Domain;

import java.util.Vector;
import java.util.HashMap;
import java.util.Collection;

import Persistance.KMeans.Point;
import Persistance.KMeans.ClusterAnalysis;
import Domain.MySqlAccessors.MySqlRecommendationProxy;
import org.apache.log4j.Logger;

public class KMeansAdapter implements IRankedItemsSet {

    static Logger logger  = Logger.getLogger("MovieSystem.Domain.KMeansAdapter");

    ClusterAnalysis jca;
    MySqlRecommendationProxy m_recommendations;
    HashBasedRecommendationSet m_kUsers;
    HashMap<String,String> m_ClusterMap;

    public KMeansAdapter(MySqlRecommendationProxy rs, int k) {
        m_recommendations = rs;
        
        Vector<Point> points = new Vector<Point>();
        for (String user : m_recommendations.getUsers()) {
            double[] v = m_recommendations.getRankAvgByGenre(user);
            Point p = new Point(v,user);
            points.add(p);
        }

		jca = new ClusterAnalysis(k, 1000, points);
		jca.startAnalysis();

        m_kUsers = new HashBasedRecommendationSet();
        m_ClusterMap = new HashMap<String, String>();
        fillKUsers();
    }

    private void fillKUsers() {
        Vector<Point>[] v = jca.ClusterOutput();
		for (int i = 0; i < v.length; i++)
		{
			Vector<Point> tempV = v[i];

            System.out.println("-----------Cluster " + i + "---------");
            m_ClusterMap.put("Cluster"+i,"Cluster"+i);
            HashMap<String,Integer> moviesSum = new HashMap<String, Integer>();
            HashMap<String,Integer> moviesAmount = new HashMap<String, Integer>();
            for (Point dpTemp : tempV) {
                System.out.print(dpTemp.getName()+", ");
                m_ClusterMap.put(dpTemp.getName(),"Cluster"+i);
                for (Recommendation r : m_recommendations.getUserItems(dpTemp.getName())) {
                    String movie = r.getMovieName();
                    if (!moviesSum.containsKey(movie)) {
                        moviesSum.put(movie,0);
                        moviesAmount.put(movie,0);
                    }
                    moviesSum.put(movie,moviesSum.get(movie)+r.getUserRank());
                    moviesAmount.put(movie,moviesAmount.get(movie)+1);
                }
            }
            System.out.println();
            System.out.println(moviesAmount.size()+" == "+moviesSum.size());
            for (String movie : moviesAmount.keySet()) {
                int rank = moviesSum.get(movie) / moviesAmount.get(movie);
                m_kUsers.add(new Recommendation("Cluster"+i,movie,"",rank));
            }
        }
        logger.info("clusters ready");
    }

    public double getRank(String user, String item) {
        String userCluster = m_ClusterMap.get(user);
        return m_kUsers.getRank(userCluster,item);
    }

    public double getAvgRank(String user) {
        String userCluster = m_ClusterMap.get(user);
        return m_kUsers.getAvgRank(userCluster);
    }

    public Collection<String> getUsers() {
        return m_kUsers.getUsers();
    }

    public Collection<String> getJointItems(String user1, String user2) {
        String userCluster1 = m_ClusterMap.get(user1);
        String userCluster2 = m_ClusterMap.get(user2);
        return m_kUsers.getJointItems(userCluster1,userCluster2);
    }

    public boolean hasRank(String user, String movie) {
        String userCluster = m_ClusterMap.get(user);
        return m_kUsers.hasRank(userCluster,movie);
    }

    public String getCluster(String user) {        
        return m_ClusterMap.get(user);
    }
}
